import { defineComponent, ref } from 'vue';
import HeaderComponent from './components/header';
import ViewNormalComponent from './components/viewNormal';
import ViewTableComponent from './components/viewTable';
import HelpTipCommandComponent from './components/helpTipCommand';
import ViewCodeComponent from './components/viewCode';
import useModule from './index.module';
import './css/dark.module.scss';
import './css/ansi.module.scss';
import styles from './index.module.scss';
import { terminalProps } from './js/terminalAttribute';
import { MESSAGE_TYPE } from './js/terminalTypes';

export default defineComponent({
  name: 'LindadayoTerminal',
  props: {
    ...terminalProps()
  },
  setup(props, { slots }) {
    const terminalContainerRef = ref(null);
    const terminalHeaderRef = ref(null);
    const terminalWindowRef = ref(null);
    const terminalInputBoxRef = ref(null);
    const terminalInputPromptRef = ref(null);
    const terminalCmdInputRef = ref(null);
    const terminalCursorRef = ref(null);
    const terminalResizeLTRef = ref(null);
    const terminalResizeLBRef = ref(null);
    const terminalResizeRTRef = ref(null);
    const terminalResizeRBRef = ref(null);
    const terminalEnFlagRef = ref(null);
    const terminalChFlagRef = ref(null);
    const terminalSearchTipsRef = ref(null);
    const terminalAskInputRef = ref(null);
    const {
      headerHeight,
      terminalLog,
      containerStyleStore,
      showInputLine,
      command,
      cursorConfig,
      searchTips,
      cp_helpTipConfig,
      ask,
      methods
    } = useModule(props, {
      terminalHeaderRef,
      terminalContainerRef,
      terminalCmdInputRef,
      terminalWindowRef,
      terminalResizeLBRef,
      terminalResizeLTRef,
      terminalResizeRTRef,
      terminalResizeRBRef,
      terminalEnFlagRef,
      terminalChFlagRef,
      terminalInputPromptRef,
      terminalInputBoxRef,
      terminalCursorRef,
      terminalSearchTipsRef,
      terminalAskInputRef
    });
    return () => (
      <main
        class={[styles.tContainer, 'tContainer']}
        ref={terminalContainerRef}
        style={containerStyleStore.value}
      >
        {methods.isDraggable() && (
          <section>
            <div class={[styles.tPoint, styles.tPointLt]} ref={terminalResizeLTRef}></div>
            <div class={[styles.tPoint, styles.tPointRt]} ref={terminalResizeRTRef}></div>
            <div class={[styles.tPoint, styles.tPointLb]} ref={terminalResizeLBRef}></div>
            <div class={[styles.tPoint, styles.tPointRb]} ref={terminalResizeRBRef}></div>
          </section>
        )}
        <section class={styles.terminal}>
          {props.showHeader && (
            <header
              class={styles.tHeaderContainer}
              ref={terminalHeaderRef}
              style={`${methods.isDraggable() ? 'cursor: move' : ''}`}
              ondblclick={methods._fullscreen}
            >
              {slots.header ? slots.header() : (
                <HeaderComponent
                  title={props.title}
                  pinned={methods.isPinned()}
                  draggable={methods.isDraggable()}
                  on-header-click={methods._triggerClick}
                />
              )}
            </header>
          )}
          <content
            class={styles.tWindow}
            ref={terminalWindowRef}
            style={{
              height: props.showHeader ? `calc(100% - ${headerHeight.value}px)` : '100%',
              marginTop: props.showHeader ? `${headerHeight.value}px` : 0,
              padding: props.enableFold ? '0 0 0 20px' : '5px 10px'
            }}
            onClick={() => methods._focus(false)}
          >
            {terminalLog.value.map((group, groupIdx) => (
              <div
                key={groupIdx}
                class={[styles.tLogBox, group.fold ? styles.tLogBoxFolded : '']}
                style={{
                  marginTop: `${props.lineSpace}px`
                }}
              >
                {methods._enableFold(group) && (
                  <span>
                    {group.fold ? (
                      <span class={[styles.tLogFoldIcon, styles.tLogFoldIconActive]} onClick={() => methods._closeGroupFold(group)}>+</span>
                    ) : (
                      <span class={[styles.tLogFoldIcon]} onClick={() => { group.fold = true }}>-</span>
                    )}
                    {!group.fold && <span class={styles.tLogFoldLine} />}
                  </span>
                )}
                {group.logs.map((item, idx) => (
                  <div key={idx} style={`margin-top: ${props.lineSpace}px;`} onClick={() => methods._closeGroupFold(group)}>
                    {item.type === MESSAGE_TYPE.CMDLINE ? (
                      <span class={[styles.tCmdLine, styles.tCrudeFont, styles.tCmdLineContent]} domPropsInnerHTML={item.content} />
                    ) : (
                      <div>
                        {(() => {
                          if (item.type === MESSAGE_TYPE.NORMAL) {
                            return (
                              <span>
                                {slots.viewNormal ? slots.viewNormal() : <ViewNormalComponent data={item} />}
                              </span>
                            )
                          } else if (item.type === MESSAGE_TYPE.HTML) {
                            return slots.html ? slots.html(item) : <div domPropsInnerHTML={item.content}></div>
                          } else if (item.type === MESSAGE_TYPE.TABLE) {
                            return slots.table ? slots.table(item) : <ViewTableComponent data={item} />
                          } else if (item.type === MESSAGE_TYPE.CODE) {
                            return slots.code ? slots.code(item) : <ViewCodeComponent data={item} />
                          } else {
                            return ''
                          }
                        })()}
                      </div>
                    )}
                  </div>
                ))}
              </div>
            ))}
            {ask.open && ask.question && (
              <div
                style={`margin: ${props.lineSpace}px 0;`}
              >
                <div style='display:inline-block;' domPropsInnerHTML={ask.question}></div>
                <input
                  type={ask.isPassword ? 'password' : 'text'}
                  ref={terminalAskInputRef}
                  v-model={ask.inputVal}
                  class={styles.tAskInput}
                  autocomplate='new-password'
                  onkeyup={methods._onAskInput}
                />
              </div>
            )}
            {showInputLine.value && (
              <p
                class={[styles.tLastLine, styles.tCrudeFont, styles.tCmdLine]}
                ref={terminalInputBoxRef}
                style={`margin-top:${props.lineSpace}px;`}
              >
                {/* 终端主机 */}
                <span class={[styles.tCmdLineContent, styles.tDisableSelect]} ref={terminalInputPromptRef}>
                  <span>{props.context}</span>
                  <span>{props.contextSuffix}</span>
                </span>
                {/* 命令指令 */}
                <span class={styles.tCmdLineContent} domPropsInnerHTML={methods._commandFormatter(command.value)}></span>
                {/* 光标 */}
                {cursorConfig.show && (
                  <span
                    class={[styles.tCursor, styles.tDisableSelect, styles[`tCursor${props.cursorStyle}`], props.cursorBlink ? styles.tCursorBlink : '']}
                    ref={terminalCursorRef}
                    style={`width:${cursorConfig.width}px;left:${cursorConfig.left};top:${cursorConfig.top};`}
                  >&nbsp;</span>
                )}
                {/* 命令输入input */}
                <input
                  type='text'
                  v-model={command.value}
                  class={[styles.tCmdInput, styles.tDisableSelect]}
                  ref={terminalCmdInputRef}
                  autofocus='autofocus'
                  autocomplete='off'
                  onfocusin={() => (cursorConfig.show = true)}
                  onkeyup={methods._onInputKeyUp}
                  onkeydown={methods._onInputKeyDown}
                  oninput={methods._onInput}
                />
              </p>
            )}
          </content>
        </section>
        {cp_helpTipConfig.value.open &&
          (slots.helpTip ? (
            slots.helpTip(cp_helpTipConfig.value.command)
          ) : (
            <HelpTipCommandComponent
              class={styles.tHelpTipBox}
              style={{
                top: `${headerHeight.value + 6}px`,
                right: '6px'
              }}
              tip-command={cp_helpTipConfig.value.command}
            />
          ))}
        {searchTips.open && (
          <div
            class={styles.tCmdTips}
            style={{
              top: `${searchTips.style.top}px`,
              left: `${searchTips.style.left}px`,
              opacity: `${searchTips.style.opacity}`
            }}
            ref={terminalSearchTipsRef}
          >
            <div class={[styles.tCmdTipsItems]}>
              {searchTips.items.map((child, childIdx) => (
                <div
                  key={childIdx}
                  class={[
                    'tCmdTipsItem', // 静态class用于js中切换选择指令时选取dom
                    styles.tCmdTipsItem,
                    childIdx === searchTips.selectedIndex ? styles.tCmdTipsItemActive : '',
                    childIdx === 0 ? styles.tCmdTipsItemFirst : ''
                  ]}
                >
                  <span class={styles.tCmdTipsContent} domPropsInnerHTML={child.content} />
                  <span class={styles.tCmdTipsDes} domPropsInnerHTML={child.description} />
                </div>
              ))}
            </div>
            <div class={styles.tCmdTipsFooter}>
              Press <strong style='color: lightsalmon'>Tab</strong> to choose the selected suggestion.
            </div>
          </div>
        )}
        <span class={[styles.tFlag, styles.tCrudeFont, styles.tCmdLine, styles.tDisableSelect]}>
          <span class={styles.tCmdLineContent} ref={terminalEnFlagRef}>a</span>
          <span class={styles.tCmdLineContent} ref={terminalChFlagRef}>我</span>
        </span>
      </main>
    )
  }
})
